﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MonitorTool
{
    public delegate void CbDelegate();
    public delegate void CbDelegate<T1>(T1 obj1);
    public delegate void CbDelegate<T1, T2>(T1 obj1, T2 obj2);
    public partial class MonitorForm : Form
    {
        public MonitorForm()
        {
            InitializeComponent();
        }
        public System.Threading.Timer tmrcheck = null;
        public string Path { get; set; } = AppDomain.CurrentDomain.BaseDirectory + "config.ini";
        private static Mutex mut = new Mutex();
        public string Filter { get; set; }
        private void MonitorForm_Load(object sender, EventArgs e)
        {
            if (!File.Exists(Path))
            {
                
                InitConfig.IniWriteValue("MONIT", "Path", "D:\\ms", Path);
                InitConfig.IniWriteValue("MONIT", "TimeInterval", "60", Path);
                InitConfig.IniWriteValue("MONIT", "NumTotal", "500", Path);
                InitConfig.IniWriteValue("MONIT", "SleepTime", "200", Path);
               
                InitConfig.IniWriteValue("MONIT", "CheckOpen", "0", Path);
                InitConfig.IniWriteValue("MONIT", "TimeSetting", "9:00&500|10:00&600", Path);
                InitConfig.IniWriteValue("MONIT", "Filter", "", Path);
                InitConfig.IniWriteValue("MONIT", "Memory", "10000", Path);
                InitConfig.IniWriteValue("MONIT", "CpuTotal", "10", Path);
            }
            txt_path.Text = InitConfig.IniReadValue("MONIT", "Path", Path);
            txt_times.Text = InitConfig.IniReadValue("MONIT", "TimeInterval", Path);
            txt_number.Text = InitConfig.IniReadValue("MONIT", "NumTotal", Path);
            txt_sleeptime.Text = InitConfig.IniReadValue("MONIT", "SleepTime", Path);
            txt_filter.Text = InitConfig.IniReadValue("MONIT", "Filter", Path);
            txt_memory.Text= InitConfig.IniReadValue("MONIT", "Memory", Path);

            txt_cpu.Text = InitConfig.IniReadValue("MONIT", "CpuTotal", Path);
            
            if (InitConfig.IniReadValue("MONIT", "NumTotal", Path)=="1")
            {
                chk_CheckOpen.Checked = true;
                txt_TimeSetting.ReadOnly = false;
            }
            else
            {
                chk_CheckOpen.Checked = false;
                txt_TimeSetting.ReadOnly = true;
            }

            txt_TimeSetting.Text = InitConfig.IniReadValue("MONIT", "TimeSetting", Path);
            bt_start.Visible = true;
            bt_stop.Visible = false;
        }

        public int Mtimes = -1;

        public int Currentnum { get; set; }


       /// <summary>
       /// 休眠时间
       /// </summary>
        public int SleepTime { get; set; }

       public string StartPath { get; set; }
        public string TimeSeting { get; set; }
        public bool CheckOpen { get; set; }

        public int MemoryTotal { get; set; } = 10000;

        public int CpuTotal { get; set; } = 10;
        private object o = new object();
        private void bt_start_Click(object sender, EventArgs e)
        {
            try
            {
                if (int.TryParse(txt_times.Text, out int ret))
                {
                    if (!int.TryParse(txt_number.Text, out int ret1))
                    {
                        ShowRich("处理个数设置错误");
                        return;
                    }

                    if (!int.TryParse(txt_sleeptime.Text, out int ret2))
                    {
                        ShowRich("延时时间设置错误");
                        return;
                    }

                    if (!Directory.Exists(txt_path.Text))
                    {
                        ShowRich("路径设置错误");
                        return;
                    }
                    if (chk_CheckOpen.Checked)
                    {
                        if (!txt_TimeSetting.Text.Contains("&"))
                        {
                            ShowRich("不同时间轮询出错");
                            return;
                        }

                    }
                    if (!int.TryParse(txt_memory.Text, out int MemoryTotal1))
                    {
                        ShowRich("内存值设置错误");
                        return;
                    }
                    if (!int.TryParse(txt_cpu.Text, out int  CpuTotal1))
                    {
                        ShowRich("内存值设置错误");
                        return;
                    }
                    txt_times.ReadOnly = true;
                    txt_number.ReadOnly = true;
                    txt_sleeptime.ReadOnly = true;
                    txt_path.ReadOnly = true;
                    txt_TimeSetting.ReadOnly = true;
                    txt_filter.ReadOnly = true;
                    chk_CheckOpen.Enabled = false;
                    TimeSeting = txt_TimeSetting.Text;
                    CheckOpen = chk_CheckOpen.Checked;
                    StartPath = txt_path.Text;
                    SleepTime = int.Parse(txt_sleeptime.Text);
                    Currentnum = Convert.ToInt32(txt_number.Text);
                    Mtimes = 1000 * Convert.ToInt32(txt_times.Text);
                    MemoryTotal = Convert.ToInt32(txt_memory.Text);
                    CpuTotal = Convert.ToInt32(txt_cpu.Text);
                    Filter = txt_filter.Text;
                    InitConfig.IniWriteValue("MONIT", "Path", StartPath, Path);
                    InitConfig.IniWriteValue("MONIT", "TimeInterval", txt_times.Text, Path);
                    InitConfig.IniWriteValue("MONIT", "NumTotal", Currentnum.ToString(), Path);
                    InitConfig.IniWriteValue("MONIT", "SleepTime", SleepTime .ToString(), Path);
                    InitConfig.IniWriteValue("MONIT", "Filter", Filter, Path);
                    InitConfig.IniWriteValue("MONIT", "Memory", MemoryTotal.ToString(), Path);
                    InitConfig.IniWriteValue("MONIT", "CpuTotal", CpuTotal.ToString(), Path);
                    if (chk_CheckOpen.Checked)
                    {
                        InitConfig.IniWriteValue("MONIT", "CheckOpen", "1", Path);
                    }
                    else
                    {
                        InitConfig.IniWriteValue("MONIT", "CheckOpen", "0", Path);
                    }
                    
                    InitConfig.IniWriteValue("MONIT", "TimeSetting", TimeSeting, Path);
                    tmrcheck = new System.Threading.Timer(CheckRun, null, Mtimes, Mtimes);
                    ShowRich("启动检查运行");
                    bt_start.Visible = false;
                    bt_stop.Visible = true;
                   Task.Factory.StartNew(delegate() 
                   {
                       StartCheck(false);
                   });
                }
                else
                {
                    ShowRich("时间设置错误");
                    return;
                }
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception);
                
            }
          
           
            
        }
        /// <summary>
        /// 检测运行情况
        /// </summary>
        public void CheckRun(object state)
        {
            try
            {
                tmrcheck.Change(Timeout.Infinite, Timeout.Infinite);
                StartCheck();
            }
            catch (Exception e)
            {
                ShowRich(e.Message);
            }
            finally
            {
                tmrcheck.Change(Mtimes, Mtimes);
            }

            
        }
        public ConcurrentDictionary<string, PerformanceCounter> PerformanceCount = new ConcurrentDictionary<string, PerformanceCounter>();
        public ConcurrentDictionary<string, PerformanceCounter> MemoryCount = new ConcurrentDictionary<string, PerformanceCounter>();
        public void StartCheck(bool flag=true)
        {
            try
            {
               
                mut.WaitOne();
             
                int AcctNum = Currentnum;
                if (CheckOpen)
                {
                    try
                    {
                        string[] array = TimeSeting.Split('|');
                        Dictionary<DateTime, int> dic = new Dictionary<DateTime, int>();
                        foreach (string item in array)
                        {
                            string[] arratyitem = item.Split('&');

                            dic.Add(Convert.ToDateTime(arratyitem[0]), Convert.ToInt32(arratyitem[1]));

                        }
                        foreach (var dickey in dic.OrderBy(p => p.Key))
                        {
                            if (dickey.Key < DateTime.Now)
                            {
                                AcctNum = dic[dickey.Key];
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        ShowRich("时间格式设置错误" + ex.Message);

                    }

                }

                Process[] ps = Process.GetProcesses();
                //杀掉
                foreach (Process p in ps)
                {
                    try
                    {
                        if (p.ProcessName.IndexOf("WerFault", StringComparison.Ordinal) != -1)
                        {

                            p.Kill();
                        }
                    }
                    catch (Exception e)
                    {

                    }

                }
                ps = Process.GetProcesses();
                //ProcessThreadCollection PTC = p.Threads;//获取其关联的线程，包括主线程
                //int num = PTC.Count.ToString();//获取线程数量

                List<int> listexist = new List<int>();
                if (Filter != null && Filter != "")
                {
                    try
                    {
                        string[] arrayf = Filter.Split('|');
                        foreach (string item in arrayf)
                        {

                            string[] arrayfiter = item.Split('-');
                            int strartnum = Convert.ToInt32(arrayfiter[0]);
                            int endtnum = Convert.ToInt32(arrayfiter[1]);
                            for (int i = strartnum; i <= endtnum; i++)
                            {
                                listexist.Add(i);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        ShowRich("过滤设置错误" + ex.Message);
                    }

                }
                for (int i = 1; i <= AcctNum; i++)
                {
                    string msname = $"ms{i.ToString()}.exe";
                    List<Process> processes = new List<Process>();
                    foreach (Process p in ps)
                    {
                        try
                        {
                            if (p.ProcessName.IndexOf("ms", StringComparison.Ordinal) != -1)
                            {
                                if (p.MainModule != null && p.MainModule.ModuleName == msname)
                                {
                                   
                                    ProcessThreadCollection PTC = p.Threads;
                                    int num = PTC.Count;
                                   
                                  
                                    try
                                    {
                                        PerformanceCounter pf1;
                                        if (MemoryCount != null && MemoryCount.ContainsKey(p.ProcessName))
                                        {
                                            pf1 = MemoryCount[p.ProcessName];
                                            
                                        }
                                        else
                                        {
                                            pf1 = new PerformanceCounter("Process", "Working Set - Private", p.ProcessName);
                                        }
                                        
                                        
                                        float currentmemory = pf1.NextValue() / 1024;
                                        if (currentmemory>MemoryTotal)
                                        {
                                            processes.Add(p);
                                            ShowRich(msname +$"内存为{currentmemory},超过{MemoryTotal},杀掉");
                                        }

                                        PerformanceCounter curtime;
                                        if (PerformanceCount!=null&& PerformanceCount.ContainsKey(p.ProcessName))
                                        {
                                            curtime = PerformanceCount[p.ProcessName];
                                        }
                                        else
                                        {
                                            curtime = new PerformanceCounter("Process", "% Processor Time", p.ProcessName);
                                            PerformanceCount.TryAdd(p.ProcessName, curtime);
                                        }
                                        
                                       
                                        float currentcppu = curtime.NextValue() / Environment.ProcessorCount;
                                        if (currentcppu>CpuTotal)
                                        {
                                            processes.Add(p);
                                            ShowRich(msname + $"CPU为{currentcppu}%,超过{CpuTotal}%,杀掉");
                                        }
                                    }
                                    catch (Exception ex1111)
                                    {
 
                                    }
                                    if (num > 4)
                                    {
                                        listexist.Add(i);
                                        break;
                                    }
                                }
                            }

                        }
                        catch (Exception e)
                        {

                        }

                    }

                    if (processes.Count>0)
                    {
                        foreach (Process item in processes)
                        {
                            try
                            {
                                item.Kill();
                                Thread.Sleep(50);
                            }
                            catch (Exception ex)
                            {
 
                            }
                        }
                    }
                }

                for (int i = 1; i <= AcctNum; i++)
                {
                    if (!listexist.Contains(i))
                    {
                        try
                        {
                            string filestart = StartPath + "\\" + $"{ i.ToString()}" + $"\\ms{ i.ToString()}.exe";
                            //Process.Start(filestart);
                            if (flag)
                            {
                                ShowRich($"ms{i.ToString()}未运行，启动ms{i.ToString()}.exe");
                            }
                            //ShowRich($"ms{i.ToString()}未运行，启动ms{i.ToString()}.exe");
                        }
                        catch (Exception e)
                        {

                        }

                        Thread.Sleep(SleepTime);
                    }
                }
                ShowRich($"检查完成");
            }
            catch (Exception ex)
            {
                ShowRich(ex.Message);

            }
            finally
            {
                mut.ReleaseMutex();
            }
        }
        private void ShowRich(string  richcontent)
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new CbDelegate<string>(this.ShowRich), richcontent);
            }
            else
            {
                this.rich_info.Text =DateTime.Now.ToString("HH:mm:ss")+"  "+ richcontent + "\r\n" + rich_info.Text;
            }
        }
        private void bt_stop_Click(object sender, EventArgs e)
        {
            bool Running = !mut.WaitOne(0, false);
            if (Running)
            {
                
                ShowRich($"正在启动不可停止");
                return;
            }
            mut.ReleaseMutex();
            tmrcheck.Change(Timeout.Infinite, Timeout.Infinite);
            txt_times.ReadOnly = false;
            txt_number.ReadOnly = false;
            txt_sleeptime.ReadOnly = false;
            txt_path.ReadOnly = false;
            txt_filter.ReadOnly = false;
            bt_start.Visible = true;
            chk_CheckOpen.Enabled = true;
            bt_stop.Visible = false;
            txt_TimeSetting.ReadOnly = false;
            ShowRich("停止检查运行");
        }

        private void toolStripMenuItemshow_Click(object sender, EventArgs e)
        {
            this.Show();
            this.WindowState = FormWindowState.Normal;
            this.Activate();
        }

        private void toolStripMenuItemHide_Click(object sender, EventArgs e)
        {
            this.Hide();
            this.WindowState = FormWindowState.Minimized;
        }

        private void toolStripMenuItemexit_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("你确定要退出程序吗？", "确认", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.OK)
            {
               
                notifyIcon1.Visible = false;
                this.Close();
                this.Dispose();
                Application.Exit();
            }
        }

        private void notifyIcon1_DoubleClick(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.Show();
                this.WindowState = FormWindowState.Normal;
                this.Activate();
            }
        }

        private void MonitorForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            try
            {
               
                this.Close();
                this.Dispose();
                Application.Exit();
            }
            catch (Exception exception)
            {
               
            }
        }

        private void MonitorForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            // 取消关闭窗体
            e.Cancel = true;
            // 将窗体变为最小化
            this.WindowState = FormWindowState.Minimized;
        }

        private void Chk_CheckOpen_CheckedChanged(object sender, EventArgs e)
        {
            if (chk_CheckOpen.Checked)
            {
                txt_TimeSetting.ReadOnly = false;

            }
            else
            {
                txt_TimeSetting.ReadOnly = true;
            }
        }
    }
}
